/*
 * @Author: TianyiWang
 * @Date: 2022-06-08 09:56:03
 * @LastEditors: TianyiWang
 * @LastEditTime: 2022-06-13 12:16:04
 * @Description: file content
 * @FilePath: /TinyWebServer/home/wty/sylar_learn/sylar/log.cc
 */
#include"log.h"
#include<typeinfo>
#include<stdarg.h>
#include"config.h"

namespace sylar{

const char* LogLevel::ToString(LogLevel::Level val){
    switch(val){
#define XX(name) \
    case LogLevel::name: return #name; break;
    XX(DEBUG);
    XX(INFO);
    XX(WARN);
    XX(ERROR);
    XX(FATAL);
#undef XX  
    default:
        return "UNKNOWN";
    }
    return "UNKNOWN";
}

LogLevel::Level LogLevel::FromString(const std::string& str)
{
#define XX(level, v) \
if (str == #v) { \
    return LogLevel::level; \
}
XX(DEBUG, debug);
XX(INFO, info);
XX(WARN, warn);
XX(ERROR, error);
XX(FATAL, fatal);

XX(DEBUG, DEBUG);
XX(INFO, INFO);
XX(WARN, WARN);
XX(ERROR, ERROR);
XX(FATAL, FATAL);
return LogLevel::UNKNOWN;
#undef XX
}

////////////////////LoggerEvent////////////////////
LogEvent::LogEvent(std::shared_ptr<Logger> logger, LogLevel::Level level
        ,const char* file, int32_t line, uint32_t elapse
        ,uint32_t thread_id, uint32_t fiber_id, uint64_t time
        ,const std::string& thread_name)
        :m_level(level)
        ,m_file(file)
        ,m_line(line)
        ,m_elapse(elapse)
        ,m_threadId(thread_id)
        ,m_fiberId(fiber_id)
        ,m_time(time)
        ,m_threadName(thread_name)
        ,m_logger(logger)
{
}

LogEvent::LogEvent(std::shared_ptr<Logger> logger ,const char* file, int32_t line, uint32_t elapse
        ,uint32_t thread_id, uint32_t fiber_id, uint64_t time
        )
        :m_file(file)
        ,m_line(line)
        ,m_elapse(elapse)
        ,m_threadId(thread_id)
        ,m_fiberId(fiber_id)
        ,m_time(time)
        ,m_logger(logger)
        {
}

LogEvent::LogEvent(std::shared_ptr<Logger> logger, LogLevel::Level level
        ,const char* file, int32_t line, uint32_t elapse
        ,uint32_t thread_id, uint32_t fiber_id, uint64_t time)
        :m_level(level)
        ,m_file(file)
        ,m_line(line)
        ,m_elapse(elapse)
        ,m_threadId(thread_id)
        ,m_fiberId(fiber_id)
        ,m_time(time) 
        ,m_logger(logger){
}

void LogEvent::format(const char *fmt, ...){
        va_list al;
        va_start(al, fmt);
        format(fmt, al);    // 调用下面的函数
        va_end(al);
}

void LogEvent::format(const char *fmt, va_list al){
		char *buf = nullptr;
		int len = vasprintf(&buf, fmt, al); //将格式化字符串输入到缓冲区
		if(len!=-1){
			m_ss<<std::string(buf, len);
			free(buf);
		}
}

LogEventWrap::LogEventWrap(LogEvent::ptr event):m_event(event){
    
}

LogEventWrap::~LogEventWrap(){
    m_event->getLogger()->log(m_event->getLevel(), m_event);    // 重点
}

///////////Logger//////////////////////////////////
Logger::Logger(const std::string &name):
    m_name(name), m_level(LogLevel::INFO){
        m_formatter.reset(new LogFormatter("%d{%Y-%m-%d %H:%M:%S}%T%t%T%N%T%F%T[%p]%T[%c]%T%f:%l%T%m%n"));

}

void Logger::log(LogLevel::Level level, LogEvent::ptr event){
    if(level>=m_level){
        auto self = shared_from_this();
        Spinlock::Lock lock(m_mutex);
        if(!m_appenders.empty()){
            for(auto i:m_appenders){
        //            std::cout<<"=============================="<<std::endl;
        //            std::cout<<"appenders"<<typeid(i).name()<<std::endl;
        //            std::cout<<event->getContent()<<std::endl;
        //            std::cout<<"logger: "<<this<<"   "<<"level: "<<level<<"   "<<"event: "<<event<<std::endl;
        //            std::cout<<self->getLevel()<<std::endl;
                i->log(self, level, event);
            }
        }else if(m_root){
            m_root->log(level, event);   // 输出目的地是LogManager构造函数中的 stdout
        }
    }
}

void Logger::addAppender(LogAppender::ptr appender){
    Spinlock::Lock lock(m_mutex);
    ///防止appender没有设置formatter,给一个默认的
    if(!appender->getFormatter()){
        Spinlock::Lock ll(appender->m_mutex);
        //appender->setFormatter(m_formatter);
        // 如果获取不到formatter，则使用logger的formatter，否则使用自己的
        //这样就不会去设置appender的hasFormatter，说明appender没有自己的formatter
        appender->m_formatter = m_formatter;  
    }
    m_appenders.push_back(appender);

}
void Logger::delAppender(LogAppender::ptr appender){
    Spinlock::Lock lock(m_mutex);   
    for(auto it=m_appenders.begin();it!=m_appenders.end();it++){
        if(*it==appender) {
            m_appenders.erase(it);
            break;
        }
    }
}

void Logger::clearAppenders(){
    Spinlock::Lock lock(m_mutex);
    m_appenders.clear();
}

void Logger::setFormatter(const std::string str){

    sylar::LogFormatter::ptr val(new sylar::LogFormatter(str));
    // formatter初始化失败直接返回
    if(val->isError()){
        std::cout<<"Logger setFormatter name="<<m_name
                 <<" value="<<str<<" invalid formatter"<<std::endl;
        return;
    }
    setFormatter(val);
}
void Logger::setFormatter(LogFormatter::ptr ptr){
    Spinlock::Lock lock(m_mutex);
    m_formatter = ptr;
    /// logger里的formatter变了，appender里继承自logger的formatter也需要改变
    for(auto &i:m_appenders){
            Spinlock::Lock ll(i->m_mutex);
        if(!i->m_hasFormatter){
            i->m_formatter = m_formatter;
        }
    }
}
LogFormatter::ptr Logger::getFormatter(){
    Spinlock::Lock lock(m_mutex);
    return m_formatter;
}

YAML::Node Logger::toYamlString(){   
    Spinlock::Lock lock(m_mutex);
    YAML::Node node;
    node["name"] = m_name;
    if (m_level != LogLevel::UNKNOWN)
    {
        node["level"] = LogLevel::ToString(m_level);
    }
    if (m_formatter)
    {
        node["formatter"] = m_formatter->getPattern();
    }

    for(auto& i : m_appenders) {
        node["appenders"].push_back(YAML::Load(i->toYamlString()));
//        std::cout<<node["appenders"]<<std::endl;
    }

    std::stringstream ss;
    ss << node;

    return node;
}

///输出不同级别的日志
void Logger::debug(LogEvent::ptr event){
    log(LogLevel::DEBUG, event);
}
void Logger::info(LogEvent::ptr event){
    log(LogLevel::INFO, event);
}
void Logger::warn(LogEvent::ptr event){
    log(LogLevel::WARN, event);
}
void Logger::error(LogEvent::ptr event){
    log(LogLevel::ERROR, event);
}
void Logger::fatal(LogEvent::ptr event){
    log(LogLevel::FATAL, event);
}

//////////////Appender////////////////////////////

///文件重新打开返回true
bool FileLogAppender::reopen(){
    Spinlock::Lock lock(m_mutex);
    if(m_filestream){
        m_filestream.close();
    }
    m_filestream.open(m_filename, std::ios::app);
    return !!m_filestream;
}

void StdoutLogAppender::log(std::shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::ptr event){
    if(level>=m_level){
        Spinlock::Lock lock(m_mutex);
        std::cout<<m_formatter->format(logger, level, event);
    }
}

std::string StdoutLogAppender::toYamlString()
{
    Spinlock::Lock lock(m_mutex);
    YAML::Node node;
    node["type"] = "StdoutLogAppender";
    if(m_level != LogLevel::UNKNOWN) {
        node["level"] = LogLevel::ToString(m_level);
    }
    if(m_hasFormatter && m_formatter) {
        node["formatter"] = m_formatter->getPattern();
    }
    std::stringstream ss;
    ss << node;
    return ss.str();
}

void FileLogAppender::log(std::shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::ptr event){
    if(level>=m_level){
        uint64_t now = time(0);
        if(now!=m_lastTime){
            reopen();   // 如果文件被删除则重新生成一个文件
            m_lastTime = now;
        }
        Spinlock::Lock lock(m_mutex);
        m_filestream<<m_formatter->format(logger, level, event);
    }
}

std::string FileLogAppender::toYamlString()
{
    Spinlock::Lock lock(m_mutex);

    YAML::Node node;
    node["type"] = "FileLogAppender";
    node["file"] = m_filename;
    if(m_level != LogLevel::UNKNOWN) {
        node["level"] = LogLevel::ToString(m_level);
    }
    if(m_hasFormatter && m_formatter) {
        node["formatter"] = m_formatter->getPattern();
    }
    std::stringstream ss;
    ss << node;
    return ss.str();
}

///////////////////LogFormatter////////////////////

class MessageFormatItem: public LogFormatter::FormatItem{
public:
    MessageFormatItem(const std::string &str=""){}
    void format(std::ostream &os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event){
        os<<event->getContent();
    }
};

class LevelFormatItem: public LogFormatter::FormatItem{
public:
    LevelFormatItem(const std::string& str=""){}
    void format(std::ostream &os, Logger::ptr logger,LogLevel::Level level, LogEvent::ptr event){
        os<<LogLevel::ToString(level);
    }
};

class StringFormatItem : public LogFormatter::FormatItem {
public:
    StringFormatItem(const std::string& str="") : FormatItem(str), m_string(str){ }
    // 格式化日志到流
    void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event){
        os << m_string;
    }
private:
    std::string m_string;
};

class ElapseFormatItem : public LogFormatter::FormatItem {
public:
    ElapseFormatItem(const std::string& str=""){ }
    // 格式化日志到流
    void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event){
        os << event->getElapse();
    }
private:
    std::string m_string;
};

class NameFormatItem : public LogFormatter::FormatItem {
public:
    NameFormatItem(const std::string& str=""){ }
    // 格式化日志到流
    void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event){
        if(event->getLogger()){
            os<<event->getLogger()->getName();
        }else{
            os<<event->getName();
        }
    }
};

class ThreadIdFormatItem : public LogFormatter::FormatItem {
public:
    ThreadIdFormatItem(const std::string& str=""){ }
    // 格式化日志到流
    void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event){
        os << event->getThreadId();
    }
};

class FiberIdFormatItem : public LogFormatter::FormatItem {
public:
    FiberIdFormatItem(const std::string& str=""){ }
    // 格式化日志到流
    void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event){
        os << event->getFiberId();
    }
};

class DateTimeFormatItem : public LogFormatter::FormatItem {
public:

    DateTimeFormatItem(const std::string& format="%Y-%m-%d %H:%M:%S"):m_format(format){
        ///判断之后可以成功显示时间
        if(m_format.empty()){
            m_format = "%Y-%m-%d %H:%M:%S";
        }
    }
    // 格式化日志到流
    void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event){
        struct tm *info = new struct tm;
        time_t rawtime = event->getTime();
        char *buffer = new char[80];
        localtime_r(&rawtime, info);
        strftime(buffer, 80, m_format.c_str(), info);
        //std::cout<<buffer<<std::endl;
        os << buffer;
        delete info;
        delete buffer;
    }
private:
    std::string m_format;
};

class FilenameFormatItem : public LogFormatter::FormatItem {
public:
    FilenameFormatItem(const std::string& str=""){ }
    // 格式化日志到流
    void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event){
        os << event->getFile();
    }
};

class LineFormatItem : public LogFormatter::FormatItem {
public:
    LineFormatItem(const std::string& str=""){ }
    // 格式化日志到流
    void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event){
        os << event->getLine();
    }
};

class ThreadNameFormatItem : public LogFormatter::FormatItem {
public:
    ThreadNameFormatItem(const std::string& str){ }
    // 格式化日志到流
    void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event){
        os << event->getThreadName();
    }
};

class TabFormatItem : public LogFormatter::FormatItem {
public:
    TabFormatItem(const std::string& str ="") {}
    void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event){
        os << "\t";
    }
};

class NewLineFormatItem : public LogFormatter::FormatItem {
public:
    NewLineFormatItem(const std::string& str = "") {}
    void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event){
        os<<std::endl;
    }
};

/// 遍历每个FormatItem，将内容按照格式一次输入到流中，返回字符串
std::string LogFormatter::format(std::shared_ptr<Logger> logger,LogLevel::Level level, LogEvent::ptr event){
    std::stringstream ss;
    for(auto &i:m_items){
        i->format(ss, logger, level, event);
    }
    return ss.str();
}

/**
 * 简单的状态机判断，提取pattern中的常规字符和模式字符
 * 
 * 解析的过程就是从头到尾遍历，根据状态标志决定当前字符是常规字符还是模式字符
 * 
 * 一共有两种状态，即正在解析常规字符和正在解析模板转义字符
 * 
 * 比较麻烦的是%%d，后面可以接一对大括号指定时间格式，比如%%d{%%Y-%%m-%%d %%H:%%M:%%S}，这个状态需要特殊处理
 * 
 * 一旦状态出错就停止解析，并设置错误标志，未识别的pattern转义字符也算出错
 * 
 * @example pattern="%d{%Y-%m-%d %H:%M:%S} [%rms]%T%t%T%N%T%F%T[%p]%T[%c]%T%f:%l%T%m%n"
 */
 ///%d [%p] %f:%l %m %n
void LogFormatter::init() {
    //按顺序存储解析到pattern项,日期类型和转移类型还有普通的字符串
    // 每个tuple包括string format type    0是普通字符，1是需要转义的
    std::vector<std::tuple<std::string, std::string, int> > vec;
    std::string nstr;
    // %d  [%p] %f %l %n
    for(size_t i = 0; i < m_pattern.size(); ++i) {
        if(m_pattern[i] != '%') {
            nstr.append(1, m_pattern[i]);
            continue;
        }

        if((i + 1) < m_pattern.size()) {
            if(m_pattern[i + 1] == '%') {
                nstr.append(1, '%');
                continue;
            }
        }

        size_t n = i + 1;
        int fmt_status = 0;
        size_t fmt_begin = 0;

        std::string str;
        std::string fmt;
        while(n < m_pattern.size()) {
            if(!fmt_status && (!isalpha(m_pattern[n]) && m_pattern[n] != '{'
                               && m_pattern[n] != '}')) {
                str = m_pattern.substr(i + 1, n - i - 1);
                break;
            }
            if(fmt_status == 0) {
                if(m_pattern[n] == '{') {
                    str = m_pattern.substr(i + 1, n - i - 1);
                    //std::cout << "*" << str << std::endl;
                    fmt_status = 1; //解析格式
                    fmt_begin = n;
                    ++n;
                    continue;
                }
            } else if(fmt_status == 1) {
                if(m_pattern[n] == '}') {
                    fmt = m_pattern.substr(fmt_begin + 1, n - fmt_begin - 1);
                    //std::cout << "#" << fmt << std::endl;
                    fmt_status = 0;
                    ++n;
                    break;
                }
            }
            ++n;
            if(n == m_pattern.size()) {
                if(str.empty()) {
                    str = m_pattern.substr(i + 1);
                }
            }
        }

        if(fmt_status == 0) {
            if(!nstr.empty()) {
                vec.push_back(std::make_tuple(nstr, std::string(), 0));
                nstr.clear();
            }
            vec.push_back(std::make_tuple(str, fmt, 1));
            i = n - 1;
        } else if(fmt_status == 1) {
            std::cout << "pattern parse error: " << m_pattern << " - " << m_pattern.substr(i) << std::endl;
            m_error = true;
            vec.push_back(std::make_tuple("<<pattern_error>>", fmt, 0));
        }
    }

    if(!nstr.empty()) {
        vec.push_back(std::make_tuple(nstr, "", 0));
    }

    static std::map<std::string, std::function<FormatItem::ptr(const std::string& str)> > s_format_items = {
#define XX(str, C) \
    {#str, [](const std::string& fmt) { return FormatItem::ptr(new C(fmt));}}

            XX(m, MessageFormatItem),           //m:消息
            XX(p, LevelFormatItem),             //p:日志级别
            XX(r, ElapseFormatItem),            //r:累计毫秒数
            XX(c, NameFormatItem),              //c:日志名称
            XX(t, ThreadIdFormatItem),          //t:线程id
            XX(n, NewLineFormatItem),           //n:换行
            XX(d, DateTimeFormatItem),          //d:时间
            XX(f, FilenameFormatItem),          //f:文件名
            XX(l, LineFormatItem),              //l:行号
            XX(T, TabFormatItem),               //T:Tab
            XX(F, FiberIdFormatItem),           //F:协程id
            XX(N, ThreadNameFormatItem),        //N:线程名称
#undef XX
    };

    for(auto& i : vec) {
        if(std::get<2>(i) == 0) {
            m_items.push_back(FormatItem::ptr(new StringFormatItem(std::get<0>(i))));
        } else {
            auto it = s_format_items.find(std::get<0>(i));
            if(it == s_format_items.end()) {
                m_items.push_back(FormatItem::ptr(new StringFormatItem("<<error_format %" + std::get<0>(i) + ">>")));
                m_error = true;
            } else {
                //std::cout<<it->second(std::get<1>(i))<<" ";
                m_items.push_back(it->second(std::get<1>(i)));
            }
        }

        //std::cout << "(" << std::get<0>(i) << ") - (" << std::get<1>(i) << ") - (" << std::get<2>(i) << ")" << std::endl;
    }

}

LogFormatter::LogFormatter(const std::string &pattern):m_pattern(pattern){
    init();
}


struct LogAppenderDefine{
int type = 0; /// 1:File   2:Stdout
LogLevel::Level level = LogLevel::INFO;
std::string formatter;
std::string file;

bool operator==(const LogAppenderDefine& oth) const{
    return oth.type==type 
    && oth.level==level 
    && oth.formatter==formatter 
    && oth.file==file;
}

};

struct LogDefine{
    std::string name;
    LogLevel::Level level = LogLevel::INFO;
    std::string formatter;
    std::vector<LogAppenderDefine> appenders;

    bool operator==(const LogDefine &ld) const{
        return ld.name==name
        && ld.level==level
        && ld.formatter==formatter
        && ld.appenders==appenders;
    }

    bool operator<(const LogDefine &ld) const{
        return name<ld.name;
    }

    bool isValid() const {
    return !name.empty();
    }
};

/**
 * @brief LexicalCast配置的偏特化
 * @para: std::string -> LogDefine
 * 
 */
template<>
class LexicalCast<std::string, LogDefine> {
public:
    LogDefine operator()(const std::string& v)
    {
        YAML::Node node = YAML::Load(v);
        LogDefine ld;
        if (!node["name"].IsDefined())  // 如果"#name"该logger没有被定义
        {
            std::cout << "log config error: name is null, " << node << std::endl;
            throw std::logic_error("log config name is null");
        }
        ld.name = node["name"].as<std::string>();
        ld.level = LogLevel::FromString(node["level"].IsDefined() ? node["level"].as<std::string>() : "");
        if (node["formatter"].IsDefined())
        {
            ld.formatter = node["formatter"].as<std::string>();
        }

        if (node["appenders"].IsDefined())
        {
            // std::cout << "==" << ld.name << " = " << node["appenders"].size() << std::endl;
            for (size_t x = 0; x < node["appenders"].size(); ++x)
            {
                auto a = node["appenders"][x];
                if (!a["type"].IsDefined())
                {
                    std::cout << "log config error: appender type is null, " << a << std::endl;
                    continue;
                }
                std::string type = a["type"].as<std::string>();
                LogAppenderDefine lad;
                if (type == "FileLogAppender")
                {
                    lad.type = 1;
                    if (!a["file"].IsDefined())
                    {
                        std::cout << "log config error: fileappender file is null, " << a << std::endl;
                        continue;
                    }

                    lad.file = a["file"].as<std::string>();
                    if (a["formatter"].IsDefined())
                    {
                        lad.formatter = a["formatter"].as<std::string>();
                    }
                }
                else if (type == "StdoutLogAppender")
                {
                    lad.type = 2;
                    if (a["formatter"].IsDefined())
                    {
                        lad.formatter = a["formatter"].as<std::string>();
                    }
                }
                else
                {
                    std::cout << "log config error: appender type is invalid, " << a
                                << std::endl;
                    continue;
                }
                ld.appenders.push_back(lad);
            }
        }
        return ld;
    }
};

template<>
class LexicalCast<LogDefine, std::string> {
public:
    std::string operator()(const LogDefine& i)
    {
        YAML::Node n;
        n["name"] = i.name;
        if (i.level != LogLevel::UNKNOWN)
        {
            n["level"] = LogLevel::ToString(i.level);
        }
        if (!i.formatter.empty())
        {
            n["formatter"] = i.formatter;
        }

        for (auto& a : i.appenders)
        {
            YAML::Node na;
            if (a.type == 1)
            {
                na["type"] = "FileLogAppender";
                na["file"] = a.file;
            }
            else if (a.type == 2)
            {
                na["type"] = "StdoutLogAppender";
            }
            if (a.level != LogLevel::UNKNOWN)
            {
                na["level"] = LogLevel::ToString(a.level);
            }
            if(!a.formatter.empty()) {
                na["formatter"] = a.formatter;
            }

            n["appenders"].push_back(na);
        }
        std::stringstream ss;
        ss << n;
        return ss.str();
    }
};


sylar::ConfigVar<std::set<LogDefine>>::ptr g_log_defines = sylar::Config::Lookup("logs", std::set<LogDefine>(), "logs config");

/**
 * @brief 事件机制触发日志配置的初始化
 * 
 */
struct LogIniter{
    LogIniter(){
        // 设置监听回调
        g_log_defines->addListener([](const std::set<LogDefine>& old_value, const std::set<LogDefine>& new_value){
            SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) <<" logger config change";
            /// lambad 函数体
            //新增
            for(auto& i:new_value){
                auto it = old_value.find(i);
                sylar::Logger::ptr logger;
                if(it==old_value.end()){
                    //新增的logger, 没有则新建一个
                    logger = SYLAR_LOG_NAME(i.name);
                }else{
                    if(!(i==*it)){
                        //修改的logger
                        logger = SYLAR_LOG_NAME(i.name);
                    }
                }
                ///修改和新增logger后进行logger内部的一些设置
                logger->setLevel(i.level);
                if(!i.formatter.empty()){
                    logger->setFormatter(i.formatter);
                }
                logger->clearAppenders();
                for(auto &a : i.appenders){
                    sylar::LogAppender::ptr ap;
                    if(a.type==1){
                        ap.reset(new FileLogAppender(a.file));
                    }else if(a.type==2){
                        ap.reset(new StdoutLogAppender);
                    }
                    ap->setLevel(a.level);
                    /// 如果存在appender的formatter那么就设置appender的formatter
                    if(!a.formatter.empty()) {
                        // SYLAR_LOG_INFO(SYLAR_LOG_ROOT())<<a.formatter;
                        LogFormatter::ptr fmt(new LogFormatter(a.formatter));
                        if(!fmt->isError()) {   // Formatter格式解析没有错误
                            ap->setFormatter(fmt);
                        } else {
                            std::cout << "log.name=" << i.name << " appender type=" << a.type
                                        << " formatter=" << a.formatter << " is invalid" << std::endl;
                        }
                    }
                    logger->addAppender(ap);
                }
            }   

            for(auto& i:old_value){
                auto it = new_value.find(i);
                if(it==new_value.end()){
                    //删除logger,通过将日志级别设置的很高来模拟删除logger的结果
                    auto logger = SYLAR_LOG_NAME(i.name);
                    logger->setLevel((LogLevel::Level)100);
                    logger->clearAppenders();
                }
            }
        });
    }
};

/// 静态的日志启动，在main函数之前启动
static LogIniter __log_init;

void LoggerManager::init(){

}

LoggerManager::LoggerManager(){
    m_root.reset(new Logger);
    m_root->addAppender(LogAppender::ptr(new StdoutLogAppender));

    /// root初始化好后要放入loggers
    m_loggers[m_root->getName()] = m_root;

    init();
}

/// 找到logger则返回，没有找到则重新创建一个
Logger::ptr LoggerManager::getLogger(const std::string &name){
    Spinlock::Lock lock(m_mutex);
    auto it = m_loggers.find(name);
    if(it!=m_loggers.end()){
        return it->second;
    }
    Logger::ptr logger(new Logger(name));
    logger->m_root = m_root;
    m_loggers[name] = logger;
    return logger;
}


std::string LoggerManager::toYamlString()
{
    Spinlock::Lock lock(m_mutex);
    YAML::Node node;
    for (auto& i : m_loggers)
    {
        node["logs"].push_back(i.second->toYamlString());
    }

    std::stringstream ss;
    ss << node;
    return ss.str();
}

}